﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;

namespace Theoreme.Teaching.AOP.Sample01
{
    public class Test_Performance
    {
        private const string category = "Test - PostSharp";

        private static readonly Stopwatch stopwatch = Stopwatch.StartNew();
        private static PerformanceCounter[] counters;

        public static void Run()
        {
            Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));

            // This forces the aspects to be initialized and 
            // the performance counters to be created.
            try
            {
                InstrumentedMethod();
            }
            catch
            {
            }

            // Initialize read-only performance counters.
            Timer timer = new Timer(TimerCallback);
            timer.Change(1000, 1000);

            string[] counterNames = new[] { "Average Time", "Invocations per Second", "% of Time", "Exceptions per Second", "% of Exceptions" };
            counters = new PerformanceCounter[counterNames.Length];
            for (int i = 0; i < counters.Length; i++)
            {
                counters[i] = new PerformanceCounter(category, counterNames[i], PerformanceCounterSettings.InstanceName);
            }

            // Execute instrumented code.
            for (int i = 0; i < 100000; i++)
            {
                try
                {
                    InstrumentedMethod();
                }
                catch
                {
                }
                Console.Write("#{0};", i);
                Thread.Sleep(50);
            }
        }


        [InstrumentAverageTime(category, "Average Time")]
        [InstrumentInvocationsPerSecond(category, "Invocations per Second")]
        [InstrumentPercentOfTime(category, "% of Time")]
        [InstrumentExceptionsPerSecond(category, "Exceptions per Second")]
        [InstrumentExceptionRate(category, "% of Exceptions")]
        [DebuggerStepThrough]
        private static void InstrumentedMethod()
        {
            int wait = (int)(100.0 + 100.0 * Math.Sin(stopwatch.ElapsedMilliseconds / 3000.0));
            Thread.Sleep(wait);

            if ((wait % 10) == 0)
                throw new Exception();
        }

        private static void TimerCallback(object state)
        {
            Console.WriteLine();
            Console.WriteLine(string.Join(", ", counters.Select(counter => counter.NextValue()).ToArray()));
        }
    }
}
